home *** CD-ROM | disk | FTP | other *** search
/ .net 2002 March / DotNetMagazine-Issue107-Coverdisc-NET107-02-03-PCMac.bin / pc / PC Software / free_browsing / DavesQckSearchDbar3-14 / dqsd.exe / src / DQSDTools / Launcher.cpp < prev    next >
C/C++ Source or Header  |  2002-07-24  |  17KB  |  616 lines

  1. // Launcher.cpp : Implementation of CLauncher
  2. #include "stdafx.h"
  3. #include "DQSDTools.h"
  4. #include "KeyboardHook.h"
  5. #include "Launcher.h"
  6. #include "Utilities.h"
  7.  
  8.  
  9. #pragma comment(lib, "Version.lib")
  10.  
  11. /////////////////////////////////////////////////////////////////////////////
  12. // CLauncher
  13.  
  14. LPCTSTR CLauncher::DQSD_REG_KEY = _T("CLSID\\{226b64e8-dc75-4eea-a6c8-abcb4d1d37ff}");
  15. LPCTSTR CLauncher::DQSD_SEC_KEY = _T("CLSID\\{226b64e8-dc75-4eea-a6c8-abcb4d1d37ff}\\SecureFiles");
  16.  
  17.  
  18. STDMETHODIMP CLauncher::SetSite(IUnknown* pUnkSite)
  19. {
  20. #if defined(DQSD_NOSECURITY) && defined(_DEBUG)
  21. #pragma message(  __FILE__ " ** WARNING! ** Compilation without security restrictions...do not distribute the resulting binary! " )
  22. #else
  23.     USES_CONVERSION;
  24.  
  25.     HRESULT hr;
  26.  
  27.     m_spUnkSite = pUnkSite;
  28.  
  29.     CComPtr<IServiceProvider> spSrvProv;
  30.     if (FAILED(hr = GetSite(IID_IServiceProvider, (void**)&spSrvProv)))
  31.         return hr;
  32.  
  33.     CComPtr<IWebBrowser2> spWebBrowser;
  34.     if (FAILED(hr = spSrvProv->QueryService(SID_SWebBrowserApp, IID_IWebBrowser2, (void**)&spWebBrowser)))
  35.         return hr;
  36.  
  37.     CComBSTR bstrURL;
  38.     if (FAILED(hr = spWebBrowser->get_LocationURL(&bstrURL)))
  39.         return hr;
  40.  
  41.     HKEY hDqsdKey;
  42.     if (ERROR_SUCCESS != RegOpenKey(HKEY_CLASSES_ROOT, DQSD_SEC_KEY, &hDqsdKey))
  43.     {
  44.         Error(IDS_ERR_UNAUTHCALLER, IID_ILauncher);
  45.         return E_FAIL;
  46.     }
  47.  
  48.     
  49.     DWORD dt;
  50.     TCHAR filebuf[MAX_PATH];
  51.     DWORD filelen = sizeof(filebuf);
  52.     DWORD idw = 0;
  53.     BOOL success = FALSE;
  54.  
  55.     while (ERROR_SUCCESS == RegEnumValue(hDqsdKey, idw, filebuf, &filelen, NULL, &dt, NULL, NULL))
  56.     {
  57.         idw++;
  58.         if (URLMatchesFilename(OLE2T(bstrURL), filebuf))
  59.         {
  60.             success = TRUE;
  61.             break;
  62.         }
  63.  
  64.         filelen = sizeof(filebuf);
  65.     }
  66.  
  67.     if (success == FALSE)
  68.     {
  69.         Error(IDS_ERR_UNAUTHCALLER, IID_ILauncher);
  70.         return E_FAIL;
  71.     }
  72.  
  73. #endif
  74.  
  75.   return S_OK;
  76. };
  77.  
  78.  
  79.  
  80. STDMETHODIMP CLauncher::SubmitForm(VARIANT idForm)
  81. {
  82.     HRESULT hr;
  83.  
  84.  
  85.     // Check for correct VARIANT type
  86.     if (idForm.vt != VT_DISPATCH)
  87.     {
  88.         Error(IDS_ERR_NEEDFORMOBJECT, IID_ILauncher );
  89.         return E_INVALIDARG;
  90.     }
  91.  
  92.  
  93.     // Switch to genuine IHTMLElement Interface
  94.     CComPtr<IHTMLElement> spHTMLElement;
  95.     if (FAILED(hr = idForm.pdispVal->QueryInterface(IID_IHTMLElement, (void**)&spHTMLElement)))
  96.     {
  97.         Error(IDS_ERR_NEEDFORMOBJECT, IID_ILauncher, hr);
  98.         return hr;
  99.     }
  100.  
  101.  
  102.     // Also keep IHTMLFormElement Interface ready
  103.     CComPtr<IHTMLFormElement> spFormElement;
  104.     CComBSTR bstrFormName;
  105.     if (FAILED(hr = idForm.pdispVal->QueryInterface(IID_IHTMLFormElement, (void**)&spFormElement)))
  106.     {
  107.         Error(IDS_ERR_NEEDFORMOBJECT, IID_ILauncher, hr);
  108.         return E_INVALIDARG;
  109.     }
  110.     if (FAILED(hr = spFormElement->get_name(&bstrFormName)))
  111.     {
  112.         Error(IDS_ERR_NEEDFORMNAME, IID_ILauncher, hr);
  113.         return E_INVALIDARG;
  114.     }
  115.  
  116.  
  117.     // Retrieve FORM from DOM, manipulate target window, and get HTML text
  118.     CComBSTR bstrTarget(_T("_self"));
  119.     spFormElement->put_target(bstrTarget);
  120.     CComBSTR bstrHTML;
  121.     spHTMLElement->get_outerHTML(&bstrHTML);
  122.     
  123.  
  124.     // Dump HTML text in temp file
  125.     {
  126.         DWORD cbPath = _MAX_PATH;
  127.         DWORD dwBytesWritten;
  128.         TCHAR szPath[_MAX_PATH];
  129.         ::GetTempPath(cbPath, szPath);
  130.  
  131.         StrNCat(szPath, _T("DQSDLaunch.html"), sizeof(szPath)/sizeof(TCHAR)-_tcslen(szPath)-1);
  132.         HANDLE hFile = ::CreateFile(szPath, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  133.         if (hFile == INVALID_HANDLE_VALUE)
  134.             return HRESULT_FROM_WIN32(::GetLastError());
  135.  
  136.         USES_CONVERSION;
  137.  
  138.         CComBSTR bstrOutput, bstrBanner;
  139.         bstrBanner.LoadString(IDS_BANNER);
  140.         bstrOutput.Append(_T("<html><body onload=\"document."));
  141.         bstrOutput.Append(bstrFormName);
  142.         bstrOutput.Append(_T(".submit();\">\n"));
  143.         bstrOutput.Append(bstrBanner);
  144.         bstrOutput.Append(_T("\n"));
  145.         bstrOutput.Append(bstrHTML);
  146.         bstrOutput.Append(_T("\n</body></html>\n"));
  147.         ::WriteFile(hFile, OLE2T(bstrOutput), bstrOutput.Length(), &dwBytesWritten, NULL);
  148.         ::FlushFileBuffers(hFile);
  149.  
  150.         ::CloseHandle(hFile);
  151.  
  152.  
  153.         // Open html associated application, passing DQSDLaunch.html
  154.         HINSTANCE hInstance = ::ShellExecute(NULL, NULL, szPath, NULL, NULL, SW_SHOWNORMAL);
  155.         if (reinterpret_cast<INT>(hInstance) <= 32)
  156.             return E_FAIL;
  157.     }        
  158.  
  159.     return S_OK;
  160. }
  161.  
  162.  
  163. STDMETHODIMP CLauncher::OpenDocument(BSTR strDoc, VARIANT* pvParameters)
  164. {
  165.     USES_CONVERSION;
  166.  
  167.     // Check for optional string parameter.  Any non-existent parameter should be indicated
  168.     // by a VARIANT of type VT_ERROR with a value of DISP_E_PARAMNOTFOUND.
  169.     HINSTANCE hInstance = NULL;
  170.     if (pvParameters && (VT_BSTR == pvParameters->vt))
  171.     {
  172.         hInstance = ::ShellExecute(NULL, NULL, OLE2T(strDoc), OLE2T(pvParameters->bstrVal), NULL, SW_SHOWNORMAL);
  173.     }
  174.     else
  175.     {
  176.         hInstance = ::ShellExecute(NULL, NULL, OLE2T(strDoc), NULL, NULL, SW_SHOWNORMAL);
  177.     }
  178.     if (reinterpret_cast<INT>(hInstance) <= 32)
  179.         return E_FAIL;
  180.  
  181.     return S_OK;
  182. }
  183.  
  184.  
  185.  
  186. STDMETHODIMP CLauncher::get_pathDefaultBrowser(BSTR *pVal)
  187. {
  188.     USES_CONVERSION;
  189.  
  190.     DWORD cbDocPath = _MAX_PATH;
  191.     TCHAR szDocPath[_MAX_PATH];
  192.     TCHAR szExePath[_MAX_PATH];
  193.  
  194.     // Create temp file with desired .html extension
  195.     ::GetTempPath(cbDocPath, szDocPath);
  196.     StrNCat(szDocPath, _T("DQSDLaunch.html"), sizeof(szDocPath)/sizeof(TCHAR)-_tcslen(szDocPath)-1);
  197.     HANDLE hFile = ::CreateFile(szDocPath, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  198.     if (hFile == INVALID_HANDLE_VALUE)
  199.         return HRESULT_FROM_WIN32(::GetLastError());
  200.     ::CloseHandle(hFile);
  201.     
  202.     // Find associated app for .html files
  203.     HINSTANCE hInstance = ::FindExecutable(szDocPath, _T(""), szExePath);
  204.     if (reinterpret_cast<INT>(hInstance) <= 32)
  205.         return E_FAIL;
  206.     
  207.     // Prepare string for shipping, and ship
  208.     *pVal = ::SysAllocString(T2OLE(szExePath));
  209.  
  210.     return S_OK;
  211. }
  212.  
  213. STDMETHODIMP CLauncher::get_Debug(VARIANT_BOOL* pbDebug)
  214. {
  215.     if (NULL == pbDebug)
  216.         return E_INVALIDARG;
  217.  
  218. #pragma warning(disable: 4310) // cast truncates constant value
  219.     *pbDebug = (m_bDebug ? VARIANT_TRUE : VARIANT_FALSE);
  220. #pragma warning(default: 4310) // cast truncates constant value
  221.  
  222.     return S_OK;
  223. }
  224.  
  225. STDMETHODIMP CLauncher::put_Debug(VARIANT_BOOL bDebug)
  226. {
  227.     m_bDebug = bDebug != VARIANT_FALSE;
  228.  
  229.     return S_OK;
  230. }
  231.  
  232.  
  233. STDMETHODIMP CLauncher::ReadFile(BSTR bstrFilename, BSTR *pbstrResult)
  234. {
  235.     USES_CONVERSION;
  236.  
  237.     // Get the full pathname after applying some defaults
  238.     TCHAR szFilename[ _MAX_PATH ];
  239.     HRESULT hr = GetFilename( W2CT( bstrFilename ), szFilename );
  240.     if ( FAILED( hr ) )
  241.         return hr;
  242.     
  243.     // Try to open the file
  244.     HANDLE hFile = ::CreateFile( szFilename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
  245.     if ( INVALID_HANDLE_VALUE == hFile )
  246.         return HRESULT_FROM_WIN32(::GetLastError());
  247.  
  248.  
  249.     // Read in the string data
  250.     TCHAR szData[ 1024 ];
  251.     DWORD dwBytesRead = 0;
  252.     CComBSTR bstrResult;
  253.     do
  254.     {
  255.         memset( szData, 0, sizeof szData );
  256.         ::ReadFile( hFile, &szData, sizeof szData - 1, &dwBytesRead, NULL );
  257.         bstrResult.Append( szData );
  258.     }
  259.     while ( dwBytesRead > 0 );
  260.     ::CloseHandle( hFile );
  261.  
  262.     // Return the file data in a big string
  263.     *pbstrResult = bstrResult.Detach();
  264.  
  265.     return S_OK;
  266. }
  267.  
  268. STDMETHODIMP CLauncher::WriteFile(BSTR bstrFilename, BSTR bstrValue)
  269. {
  270.     USES_CONVERSION;
  271.  
  272.     // Get the full pathname after applying some defaults
  273.     TCHAR szFilename[ _MAX_PATH ];
  274.     HRESULT hr = GetFilename( W2CT( bstrFilename ), szFilename );
  275.     if ( FAILED( hr ) )
  276.         return hr;
  277.     
  278.     HANDLE hFile = ::CreateFile( szFilename, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  279.     if ( INVALID_HANDLE_VALUE == hFile )
  280.         HRESULT_FROM_WIN32(::GetLastError());
  281.  
  282.     DWORD dwBytesWritten = 0;
  283.     BOOL bResult = ::WriteFile( hFile, W2CT( bstrValue ), lstrlenW( bstrValue ), &dwBytesWritten, NULL );
  284.     ::FlushFileBuffers( hFile );
  285.     ::CloseHandle( hFile );
  286.     
  287.     if ( 0 == bResult )
  288.         HRESULT_FROM_WIN32(::GetLastError());
  289.  
  290.     return S_OK;
  291. }
  292.  
  293. // Private methods
  294.  
  295. HRESULT CLauncher::GetFilename( LPCTSTR szName, LPTSTR szResult, LPCTSTR pszDefaultExt /*= _T(".txt")*/ )
  296. {
  297.     USES_CONVERSION;
  298.  
  299.     // Get the installation directory from the registry
  300.     CRegKey rk;
  301.     if ( ERROR_SUCCESS != rk.Open( HKEY_CLASSES_ROOT, DQSD_REG_KEY, KEY_READ ) )
  302.     {
  303.         Error(IDS_ERR_REGKEYNOTFOUND, IID_ILauncher);
  304.         return E_UNEXPECTED;
  305.     }
  306.  
  307.     TCHAR szInstallDir[ _MAX_PATH ];
  308.     DWORD dwCount = sizeof( szInstallDir );
  309.     if ( ERROR_SUCCESS != rk.QueryValue( szInstallDir, _T("InstallDir"), &dwCount ) )
  310.     {
  311.         Error(IDS_ERR_REGKEYNOTFOUND, IID_ILauncher);
  312.         return E_UNEXPECTED;
  313.     }
  314.  
  315.     // Add the install directory and an extension if not supplied
  316.     ::PathCombine( szResult, szInstallDir, szName );
  317.     ::PathAddExtension( szResult, pszDefaultExt );
  318.  
  319.     return S_OK;
  320. }
  321.  
  322. STDMETHODIMP CLauncher::GetProtocolHandler(BSTR bstrProtocol, BSTR *pbstrHandler)
  323. {
  324.     USES_CONVERSION;
  325.  
  326.     TCHAR szProtocolHandlerKey[ 128 ];
  327.     StrCpyN( szProtocolHandlerKey, W2T( bstrProtocol ), sizeof(szProtocolHandlerKey)/sizeof(TCHAR));
  328.     StrNCat( szProtocolHandlerKey, _T("\\shell\\open\\command"), sizeof(szProtocolHandlerKey)/sizeof(TCHAR)-lstrlenW(bstrProtocol)-1);
  329.  
  330.     TCHAR szProtocolHandler[ _MAX_PATH ];
  331.     DWORD dwCount = sizeof( szProtocolHandler );
  332.  
  333.     CRegKey rk;
  334.     if ( ( ERROR_SUCCESS != rk.Open( HKEY_CLASSES_ROOT, szProtocolHandlerKey, KEY_READ ) )
  335.          ||
  336.          ( ERROR_SUCCESS != rk.QueryValue( szProtocolHandler, _T(""), &dwCount ) ) )
  337.     {
  338.         Error(IDS_ERR_PROTOCOLNOTFOUND, IID_ILauncher);
  339.         return E_UNEXPECTED;
  340.     }
  341.  
  342.     *pbstrHandler = ::SysAllocString( T2W( szProtocolHandler ) );
  343.  
  344.     return S_OK;
  345. }
  346.  
  347. STDMETHODIMP CLauncher::GetFiles(BSTR bstrFileSpec, BSTR *pbstrFiles)
  348. {
  349.     USES_CONVERSION;
  350.  
  351.     TCHAR szFilename[ _MAX_PATH ];
  352.     HRESULT hr = GetFilename( W2CT( bstrFileSpec ), szFilename, _T("*.*") );
  353.     if ( FAILED( hr ) )
  354.     {
  355.         Error(IDS_ERR_FILENOTFOUND, IID_ILauncher, hr);
  356.         return hr;
  357.     }
  358.  
  359.     WIN32_FIND_DATA fd;
  360.     memset( &fd, 0, sizeof(fd) );
  361.     HANDLE handle = ::FindFirstFile( szFilename, &fd );
  362.     if (INVALID_HANDLE_VALUE == handle)
  363.     {
  364.         Error(IDS_ERR_FILENOTFOUND, IID_ILauncher, HRESULT_FROM_WIN32(::GetLastError()));
  365.         return HRESULT_FROM_WIN32(::GetLastError());
  366.     }
  367.  
  368.     CComBSTR bstrFiles( fd.cFileName );
  369.     while ( ::FindNextFile( handle, &fd ) )
  370.     {
  371.         if ( !StrCmp( fd.cFileName, _T(".") ) || !StrCmp( fd.cFileName, _T("..") ) )
  372.             continue;
  373.  
  374.         bstrFiles.Append( _T("\n") );
  375.         bstrFiles.Append( fd.cFileName );
  376.     }
  377.  
  378.     *pbstrFiles = bstrFiles.Detach();
  379.  
  380.     return S_OK;
  381. }
  382.  
  383. //
  384. // This is nothing to do with the launcher - I've just piggybacked it on to save
  385. // creating another class/interface
  386. //
  387. STDMETHODIMP CLauncher::InstallKeyboardHook(LPDISPATCH pDispDocument)
  388. {
  389.     return KeyboardHookInstall(UtilitiesFindDQSDWindow(pDispDocument), m_hKeyboardHook);
  390. }
  391.  
  392. STDMETHODIMP CLauncher::RegisterHotKey(long hotkeyVkCode, BSTR bstrModifierName, LPDISPATCH pDispDocument)
  393. {
  394.     USES_CONVERSION;
  395.  
  396.     return KeyboardInstallHotkey(hotkeyVkCode, W2T(bstrModifierName), &m_hHotkeyNotificationWindow, pDispDocument);
  397. }
  398.  
  399. //
  400. // This allows mapping of a virtual keycode to a character code
  401. // sent with WM_CHAR in KeyboardProc.  It prevents having to modify
  402. // KeyboardProc for every mapping
  403. STDMETHODIMP CLauncher::MapKeyCode(long lVKCode, long lCharCode)
  404. {
  405.     g_mapKeyCodeToCharCode[ lVKCode ] = lCharCode;
  406.     return S_OK;
  407. }
  408.  
  409.  
  410. STDMETHODIMP CLauncher::get_VersionIsCorrect(int v1, int v2, int v3, int v4, VARIANT_BOOL *pVal)
  411. {
  412.     // Check if our version resource is same or later version than 
  413.     // the one specified by the script in v1.v2.v3.v4
  414.  
  415.     try
  416.     {
  417. //        LPVOID pVersion;
  418. //        HRSRC hVerRes;
  419. //        HGLOBAL hVerResMem;
  420.         VS_FIXEDFILEINFO* pFixInfo;
  421.  
  422.         ATLTRACE("CLauncher: Starting get_VersionIsCorrect\n");
  423.  
  424.         TCHAR moduleName[MAX_PATH+1];
  425.         GetModuleFileName(_Module.GetModuleInstance(), moduleName, MAX_PATH);
  426.         DWORD dummyZero;
  427.         DWORD versionSize = GetFileVersionInfoSize(moduleName, &dummyZero);
  428.         if(versionSize == 0)
  429.         {
  430.             return Error(IDS_ERR_VERSION_RESOURCE, IID_ILauncher, E_FAIL);
  431.         }
  432.         BYTE* pData = new BYTE[versionSize];
  433.         if(pData == NULL)
  434.         {
  435.             return Error(IDS_ERR_VERSION_RESOURCE, IID_ILauncher, E_FAIL);
  436.         }
  437.         if(!GetFileVersionInfo(moduleName, NULL, versionSize, pData))
  438.         {
  439.             delete [] pData;
  440.             return Error(IDS_ERR_VERSION_RESOURCE, IID_ILauncher, E_FAIL);
  441.         }
  442. /*    
  443.         hVerRes = FindResource(_Module.GetResourceInstance(), MAKEINTRESOURCE(VS_VERSION_INFO), RT_VERSION);
  444.         if(hVerRes == NULL)
  445.         {
  446.             return Error(IDS_ERR_VERSION_RESOURCE, IID_ILauncher, E_FAIL);
  447.         }
  448.         hVerResMem = LoadResource (_Module.GetResourceInstance(), hVerRes) ;
  449.         if(hVerResMem == NULL)
  450.         {
  451.             return Error(IDS_ERR_VERSION_RESOURCE, IID_ILauncher, E_FAIL);
  452.         }
  453.         pVersion = LockResource (hVerResMem) ;
  454.         if(pVersion == NULL)
  455.         {
  456.             return Error(IDS_ERR_VERSION_RESOURCE, IID_ILauncher, E_FAIL);
  457.         }
  458. */
  459.         ATLTRACE("CLauncher: About to query value\n");
  460.  
  461.         UINT length;
  462.         pFixInfo = NULL;
  463.         if(!VerQueryValue(pData, _T("\\"), (LPVOID*)&pFixInfo, &length))
  464.         {
  465.             delete [] pData;
  466.             return Error(IDS_ERR_VERSION_RESOURCE, IID_ILauncher, E_FAIL);
  467.         }
  468.  
  469.         ATLTRACE("CLauncher: value queried\n");
  470.  
  471.         int dllV1, dllV2, dllV3, dllV4;
  472.         dllV1 = pFixInfo->dwProductVersionMS >> 16;
  473.         dllV2 = pFixInfo->dwProductVersionMS & 0xffff;
  474.         dllV3 = pFixInfo->dwProductVersionLS >> 16;
  475.         dllV4 = pFixInfo->dwProductVersionLS & 0xffff;
  476.  
  477.         ATLTRACE("CLauncher: DLL Version %d.%d.%d.%d\n", dllV1, dllV2, dllV3, dllV4);
  478.  
  479.         // Assume we're going to pass
  480. #pragma warning(disable: 4310) // cast truncates constant value
  481.         *pVal = VARIANT_TRUE;
  482. #pragma warning(default: 4310) // cast truncates constant value
  483.  
  484.         // Test the version in order from MS to LS
  485.         // This could have been done as one 64 bit comparison, but...
  486.         if(dllV1 < v1)
  487.         {
  488.             *pVal = VARIANT_FALSE;
  489.         }
  490.         else if(dllV2 < v2)
  491.         {
  492.             *pVal = VARIANT_FALSE;
  493.         }
  494.         else if(dllV3 < v3)
  495.         {
  496.             *pVal = VARIANT_FALSE;
  497.         }
  498.         else if(dllV4 < v4)
  499.         {
  500.             *pVal = VARIANT_FALSE;
  501.         }
  502.  
  503.         delete [] pData;
  504.  
  505.         return S_OK; 
  506.     }
  507.     catch(...)
  508.     {
  509.         return Error(IDS_EXCEPTION_IN_VERSION_CHECK, IID_ILauncher, E_FAIL);
  510.     }
  511. }
  512.  
  513.  
  514. __declspec(dllexport) void CALLBACK RestartExplorer(HWND hParent, HINSTANCE hInst, LPTSTR lpCmdLine, int nShow)
  515. {
  516.     UNREFERENCED_PARAMETER(hParent);
  517.     UNREFERENCED_PARAMETER(hInst);
  518.     UNREFERENCED_PARAMETER(lpCmdLine);
  519.     UNREFERENCED_PARAMETER(nShow);
  520.  
  521.     HWND hwndShell = FindWindow("Progman", NULL);
  522.     ::PostMessage(hwndShell, WM_QUIT, 0, 0L);
  523.     ::WinExec("Explorer.exe",SW_SHOW);
  524. }
  525.  
  526. DWORD WINAPI ShutdownThread(void* pParam)
  527. {
  528.     HWND hDQSDWnd = (HWND)pParam;
  529.  
  530.     // Wait for DQSD to be gone
  531.     LONG startTime = GetTickCount();
  532.     while(((LONG)GetTickCount() - startTime) < 10000)
  533.     {
  534.         if(!IsWindow(hDQSDWnd))
  535.         {
  536.             // We're gone
  537.  
  538.             // Restart Explorer
  539.             RestartExplorer(NULL,NULL,NULL,0);
  540.             return 0;
  541.         }
  542.         Sleep(100);
  543.     }
  544.     return 0;
  545. }
  546.  
  547.  
  548. STDMETHODIMP CLauncher::ShutdownBar(LPDISPATCH pDispDocument)
  549. {
  550. //    return Error(_T("Shutdown bar not implemented yet..."), IID_ILauncher, E_NOTIMPL);
  551.  
  552.  
  553.     HWND hDQSDWnd = UtilitiesFindDQSDWindow(pDispDocument);
  554.     if(hDQSDWnd == NULL)
  555.     {
  556.         return Error(_T("DQSD was not found on the taskbar"), IID_ILauncher, E_FAIL);
  557.     }
  558.  
  559.     // The window hierachy goes 
  560. //         _T("Shell_TrayWnd"), 
  561. //        _T("ReBarWindow32"), 
  562. //        _T("OCHost"), 
  563. //        _T("Shell Embedding"), 
  564. //        _T("Shell DocObject View"), 
  565. //        _T("Internet Explorer_Server") <== This is us
  566.  
  567.  
  568.     HWND hRebarBand = GetParent(GetParent(GetParent(hDQSDWnd)));
  569.     HWND hRebar = GetParent(hRebarBand);
  570.  
  571.     ATLTRACE("Rebar: 0x%x, Pane 0x%x\n", hRebar, hRebarBand);
  572.  
  573.     int nBands = ::SendMessage(hRebar, RB_GETBANDCOUNT, 0, 0);
  574.     for(int nBand = 0; nBand < nBands; nBand++)
  575.     {
  576.         REBARBANDINFO info;
  577.         ZeroMemory(&info, sizeof(info));
  578.         info.cbSize = sizeof(info);
  579.         info.fMask = RBBIM_CHILD;
  580.  
  581.         if(::SendMessage(hRebar, RB_GETBANDINFO, nBand, (LPARAM)&info))
  582.         {
  583.             ATLTRACE("Band %d - hWnd = 0x%x\n", nBand, info.hwndChild);
  584.  
  585.             if(info.hwndChild == hRebarBand)
  586.             {
  587.                 // We've found our band - shut it down
  588.                 ::SendMessage(hRebar, RB_SHOWBAND, nBand, FALSE);
  589.                 ::SendMessage(hRebar, RB_DELETEBAND, nBand, 0);
  590.  
  591.                 ATLTRACE("Destroying band window: 0x%x\n", hRebarBand);
  592.                 DestroyWindow(hRebarBand);
  593.  
  594.                 DWORD threadId;
  595.                 ::CreateThread(NULL, 0, ShutdownThread, hDQSDWnd,0, &threadId);
  596.  
  597.                 return S_OK;
  598.             }
  599.         }
  600.     }
  601.  
  602.     return Error(_T("Failed to shut DQSD bar"), IID_ILauncher, E_FAIL);
  603. }
  604.  
  605. STDMETHODIMP CLauncher::RefreshTrayIcons()
  606. {
  607.     static DWORD result;
  608.     UINT msg = ::RegisterWindowMessage(_T("TaskbarCreated"));
  609.  
  610.     ATLTRACE("DQSDTools: Refreshing tray icons (msg 0x%x)\n", msg);
  611.  
  612.     ::SendMessageTimeout(HWND_BROADCAST, msg, 0, 0, SMTO_ABORTIFHUNG, 1000, &result);
  613.  
  614.     return S_OK;
  615. }
  616.